package com.wonders.common.ws.client;

import java.io.UnsupportedEncodingException;
import java.security.PrivateKey;

import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.encoding.XMLType;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.wonders.common.config.manager.instance.PropertiesManager;
import com.wonders.common.constant.CommonConstant;
import com.wonders.common.parse.jaxb.JaxbService;
import com.wonders.common.parse.jaxb.config.JaxbConfig;
import com.wonders.common.parse.jaxb.entity.vo.XsdConfig;
import com.wonders.common.ws.constant.XtptConstant;
import com.wonders.common.ws.entity.vo.XtptMsg;
import com.wonders.common.ws.mapping.bean.global.Head;
import com.wonders.common.ws.util.XtptUtil;
import com.wonders.framework.exception.FrameworkException;
import com.wonders.framework.util.FileUtil;
import com.wonders.framework.util.security.RsaUtil;

/**
 * 协同平台1.0客户端
 * 
 * @author WuBin
 * 
 */
@Component
public class XtptOldWsClient {

	private Logger logger = LoggerFactory.getLogger(XtptOldWsClient.class);

	@Autowired
	private JaxbConfig jaxbConfig;

	@Autowired
	private JaxbService jaxbService;

	@Autowired
	private PropertiesManager propertiesManager;

	/**
	 * 接口调用私钥
	 */
	private PrivateKey privateKey;

	/**
	 * 获取私钥
	 * 
	 * @return
	 */
	private PrivateKey getPrivateKey() {
		if (privateKey == null) {
			privateKey = RsaUtil
					.parsePrivateKey(FileUtil
							.getFileStreamByClasspath("com/wonders/module/ws/key/O90000"));
		}
		return privateKey;
	}

	/**
	 * 接口调用
	 * 
	 * @param key
	 *            业务主键
	 * @param reqDate
	 *            数据
	 * @return 调用结果
	 */
	public XtptMsg request(String key, Object reqDate) {
		if (StringUtils.isEmpty(key) || reqDate == null) {
			throw new FrameworkException("接口调用参数不足");
		}
		Head globalHead = XtptUtil.generateRequestHead(key);
		XtptMsg xtptRequest = new XtptMsg();
		xtptRequest.setHead(globalHead);
		xtptRequest.setBody(reqDate);
		Object[] request = packRequest(xtptRequest);
		logger.info("请求报文:{}", xtptRequest.getXml());
		byte[] response = callService(request);
		XtptMsg xtptResponse = resovleResponse(key, response);
		logger.info("响应报文:{}", xtptResponse.getXml());
		return xtptResponse;
	}

	private Object[] packRequest(XtptMsg xtptRequest) {
		String key = StringUtils.join(xtptRequest.getHead().getSysCode(), "_",
				xtptRequest.getHead().getBusCode());
		XsdConfig xsdConfig = jaxbConfig.getXsdConfig(key,
				CommonConstant.Interaction.REQ);
		Object tradeMsg;
		try {
			tradeMsg = xsdConfig.getClazz().newInstance();
			PropertyUtils.setProperty(tradeMsg, "data", xtptRequest.getBody());
			PropertyUtils.setProperty(tradeMsg, "head", xtptRequest.getHead());
			String xml = jaxbService.toXml(key, CommonConstant.Interaction.REQ,
					tradeMsg);
			xtptRequest.setXml(xml);
			return new Object[] {
					XtptConstant.SIGNATURE_FLAG,
					xml,
					RsaUtil.sign(getPrivateKey(),
							xml.getBytes(XtptConstant.ENCODING)) };
		} catch (Exception e) {
			throw new FrameworkException("封装请求数据失败", e);
		}
	}

	/**
	 * 调用协同平台
	 * 
	 * @param request
	 *            请求数据
	 * @return 响应数据
	 */
	private byte[] callService(Object[] request) {
		try {
			Service service = new Service();
			Call call = (Call) service.createCall();
			call.setTargetEndpointAddress(propertiesManager.getXtptUrl());
			call.setOperationName(new QName(
					"http://jws.wsscclib.wondersgroup.com", "dispatch"));
			call.addParameter("flag", XMLType.XSD_BYTE, ParameterMode.IN);
			call.addParameter("xml", XMLType.XSD_STRING, ParameterMode.IN);
			call.addParameter("signature", XMLType.XSD_BASE64, ParameterMode.IN);
			call.setReturnType(XMLType.XSD_BASE64);
			byte[] ret = (byte[]) call.invoke(request);
			return ret;
		} catch (Exception e) {
			throw new FrameworkException("接口调用失败", e);
		}
	}

	/**
	 * 解析响应数据
	 * 
	 * @param key
	 *            业务主键
	 * @param response
	 *            响应内容
	 * @param encoding
	 *            编码
	 * @return 调用结果
	 */
	private XtptMsg resovleResponse(String key, byte[] response) {
		String xml = getResponseXml(response);
		Object tradeMsg = jaxbService.fromXML(key,
				CommonConstant.Interaction.RES, xml);
		XtptMsg xtptResponse = new XtptMsg();
		xtptResponse.setXml(xml);
		Head head = null;
		try {
			head = (Head) PropertyUtils.getProperty(tradeMsg, "head");
			xtptResponse.setHead(head);
			xtptResponse.setBody(PropertyUtils.getProperty(tradeMsg, "data"));
		} catch (Exception e) {
			throw new FrameworkException("解析响应数据失败", e);
		}
		XtptUtil.parseResponseHead(xtptResponse, head);
		return xtptResponse;
	}

	/**
	 * 获取字节
	 * 
	 * @param xml
	 *            报文
	 * @return 字节
	 */
	private static String getResponseXml(byte[] response) {
		try {
			return new String(response, 1, response.length - 1,
					XtptConstant.ENCODING);
		} catch (UnsupportedEncodingException e) {
			throw new FrameworkException("转换字符出错", e);
		}
	}

}
